<?php
/**
 * author:du
 * time:2024.2.14
 * feature:公共函数
 */
function _format_user_info($user, $target){
    // 需要转换格式的字段 总共8个
    $keys = ['stage', 'idol', 'task', 'activity', 'limit', 'career', 'backpack', 'achievement', 'trial', 'challenge','guide'];
    foreach($keys as $k => $v){
        if($target == 'json'){
            if(is_array($user[$v])){
                $user[$v] = json_encode($user[$v], true);
            }
        }
        if($target == 'array'){
            if(is_string($user[$v])){
                $user[$v] = json_decode($user[$v], true); 
            }
        }
    }
    return $user;
}
/*
* du 2025.2.16
* 读取json配置文件
* 用于读前端过来的配置表
* Summary of _read_json_file
* @param mixed $file_name
* @return $json_data
*/
function _read_json_file($file_name){
    // 设置文件路径
    $file_name = 'GameConfig/Datas/' . $file_name . '.json';
    // 读取文件
    $json_data = file_get_contents($file_name);
    // 解析json数据
    $json_data = json_decode($json_data, true);
    return $json_data;
}

/**
 * du 2025.2.16
 * 读取配置表
 * Summary of _get_config_table
 * @param mixed $table 表名称
 * @return object $config_data 配置表数据
 */
function _get_config_table(){
    // 要先把函数写成变量，下面这句
    $loader = '_read_json_file';
    $table = new Game\Org\Tables( $loader );
    return $table;
}
/**
 * du 2025.2.16
 * 读取物品表
 * Summary of _get_item_table
 * @return object $item_data 物品表数据
 */
function _get_item_table(){
    return _get_config_table()->getTbItem(); 
}
/**
 * Summary of _check_action_match
 * 辅助函数，用来判断请求action是否匹配
 * @param mixed $action_url 请求的action URL
 * @param mixed $action_params 请求的action参数
 * @param mixed $params_logic 参数匹配逻辑，默认为'or'
 * @return bool
 */
function _check_action_match($action_url, $action_params = null, $params_logic = 'or'){
    $match_result = false;
    // 获取当前请求的action URL和参数
    $current_action_url = __ACTION__;
    if(fnmatch(strtolower($action_url), strtolower($current_action_url))){
        $match_result = true;
        if($action_params){
            $match_result = false;
            // 遍历参数，判断是否匹配
            foreach($action_params as $k => $v){
                // 判断参数是否匹配，或关系，可以加个字段来确定是与还是或关系
                switch($params_logic){
                    case 'or':
                        if(I($v[0]) == $v[1]){
                            $match_result = true;
                            break;
                        }
                        break;
                    case 'and':
                        $match_result = true;
                        if(I($v[0]) != $v[1]){
                            $match_result = false;
                            break;
                        }
                        break;
                    default: break;
                }
            }
        }
    }
    return $match_result;
}

/**
 * du 2025.2.16
 * 根据路径校验每日限定
 * Summary of _check_daily_limit
    * @param mixed $user 用户信息
    * @return $res 校验结果 true 表示通过 false 表示失败    
 */
function _check_user_limit($user){
    // 校验每日限制，先把每日限制转成数组，再遍历
    $limit_list = _get_config_table()->getTbLimit()->getDataList();
    // 遍历限制列表，判断是否超出限制
    foreach($limit_list as $k => $v){
        $limit_match = false;
        // 判断请求的URL是否匹配
        if(__ACTION__ == $v->actionUrl){
            $limit_match = true;
            // 如果限制项要求有参数，判断请求的参数是否匹配
            if($v->actionParams){
                $limit_match = false;
                foreach($v->actionParams as $k2 => $v2){
                    // 判断参数是否匹配，或关系，可以加个字段来确定是与还是或关系
                    switch($v->paramsLogic){
                        case 'or':
                            if(I($v2[0]) == $v2[1]){
                                $limit_match = true;
                                break;
                            }
                            break;
                        case 'and':
                            if(I($v2[0]) == $v2[1]){
                                $limit_match = true;
                            }
                            else{
                                $limit_match = false;
                                break;
                            }
                            break;
                        default: break;
                    }
                }
            }
        }
        // 匹配到对应的限制项，判断数量是否超过上限
        if($limit_match){
            // 如果限制项匹配，判断数量是否超过上限
            if($user['limit'][$v->id]['count'] >= $v->maxLimit && $user['limit'][$v->id]['expire_time'] > time()){
                // 如果超过上限，返回失败
                return false;
            }
        }
    }
    return true;
}

/**
 * du 2025.2.16
 * 日志记录
 * Summary of _write_user_log
 * @param mixed request
 * @param mixed params 
 * @param mixed result
 * @return string log
 */
function _write_user_log($uid, $request, $params = null, $result = null){
    $log = time() . ' ';
    $log .= $request . ' ';
    if(is_array($params)){
        $log .= json_encode($params); 
    }else{
        $log .= $params;
    }
    if($result){
        $log .= ' ';
        if(is_array($result)){
            $log .= json_encode($result);
        }else{
            $log .= $result;
        }
    }
    $filepath = 'GameLog/user/'. $uid. '.log';
    file_put_contents($filepath, $log. "\n", FILE_APPEND);
    return $log;
}


/**
 * du 2025.2.10
 * 根据经验值获取等级
 * Summary of _get_level_by_exp
 * @param mixed $exp
 * @return $level
 */
function _get_level_by_exp($exp){
    $level = 1;
    // 经验值对应等级
    foreach(_get_config_table()->getTbExp()->getDataList() as $v){
        if($exp >= $v->totalExp){
            $level = $v->id;
        }
    }
    return $level;
}

/**
 * du 2025.2.10
 * 根据好感度获取羁绊等级
 * Summary of _get_level_by_exp
 * @param mixed $exp
 * @param mixed $favorability
 * @return $idol_level
 */
function _get_idol_level_by_favorability($favorability){
    $idol_level = 1;
    // 经验值对应等级
    $idol_level = 0;
    foreach(_get_config_table()->getTbFavorability()->getDataList() as $v){
        if($favorability >= $v->totalFavorability){
            $idol_level = $v->id;
        }
    }

    return $idol_level;
}

/**
 * du 2025.6 18
 * 根据product_id抽商品
 * @param mixed $product_id
 * @return $item_list
 */
function _get_item_by_product_id($product_id){
    // 先抽取皮肤品质
    $quality = _get_quality_by_weight(_get_config_table()->getTbProduct()->get($product_id)->qualityWeight);
    // 配置表中品质与值的映射关系
    // 理论上应该用配置表中的item.EQuality
    $quality_map = [
        2 => 'N', 3 => 'R', 4 => 'SR', 5 => 'SSR', 6 => 'SP'
    ];
    // 对应品质下在商店中可抽取的皮肤
    $item_range = [];
    foreach(_get_item_table()->getDataList() as $v){
        if(!$v->inShop){
            continue;
        }
        if($quality_map[$v->quality] == $quality){
            $item_range[] = $v->id;
        }
    }
    return [$item_range[array_rand($item_range)] => 1];
}
/**
 * 根据商城配置表的weight来抽取品质
 * Summary of _get_quality_by_weight
 * @param mixed $weight 权重数组
 * @return string
 */
function _get_quality_by_weight($weight){
    $random = rand(0, 99);
    $res = 0;
    $total_weight = 0;
    for($i = 0; $i < sizeof($weight); $i ++){
        $total_weight += $weight[$i];
        if($random < $total_weight){
            $res = $i;
            break;
        }
    }
    $quality_map = [
        'N', 'R', 'SR', 'SSR', 'SP'
    ];
    return $quality_map[$res];
}
/**
 * du 2025.2.10
 * 根据用户背包内的物品数量，来抽取奖励
 * Summary of _get_reward_by_backpack
 * @param mixed $backpack
 * @param mixed $reward_rule
 * @return $reward
 * 
 */
function _get_reward_by_backpack($backpack){
    // 分三大类
    // 1. 任务奖励；2. 成功奖励；3. 失败奖励
    // 先把徽章以外的物品过滤掉
    $tmp_backpack = [];
    $r_badge = [20002, 20003, 20004, 20005, 20006, 20007];
    foreach($backpack as $k => $v){
        // 2开头的是徽章
        if(($k > 20000 && $k < 30000)){
            $tmp_backpack[$k] = $v;
        }
    }
    return $tmp_backpack;
}



/**
 * du 2025.2.16
 * 更新实时羁绊下玩家助力排行缓存
 * Summary of _update_user_rank_cache
 * @param mixed $uid
 * @param mixed $support
 * @param mixed $idol_id
 * @param mixed $update_time
 * @param mixed $data : uid, support, update_time
 * @return
 */
function _update_user_rank_cache($data, $idol_id, $mode){
    // 读取当前排名缓存
    $res = S('rank_idol_user_' . $idol_id . '_' . $mode);
    // 如果缓存不存在 就不管
    if(!$res){
        return false;
    }
    // 直接对比最后一项
    $last = $res[sizeof($res) - 1];
    // 查看玩家的信息能不能进榜
    if($data['support'] < $last['support']){
        return false;
    }else if($data['support'] == $last['support']){
        // 如果支持值相同，更新时间更晚的不进榜
        if($$data['update_time'] < $last['update_time']){
            return false;
        }
    }
    // 更新缓存
    foreach($res as $k => $v){
        if($v['uid'] == $data['uid']){
            unset($res[$k]);
            break;
        }
    }
    // 这里没有传头像和昵称，取一下
    $user_info = D('GameUser')->_get_game_user_info($data['uid'], 'nickname, avatar_url');
    $data['nickname'] = $user_info['nickname'];
    $data['avatar'] = $user_info['avatar_url'];
    array_push($res, $data);
    usort($res, function($a, $b){
        if($a['support'] !== $b['support']){
            return $b['support'] - $a['support'];
        }
        return $a['update_time'] - $b['update_time'];
    });
    $res = array_slice($res, 0, 1000);
    S('rank_idol_user_' . $idol_id . '_' . $mode, $res, _get_rank_expire_time());
    return true;
}

/**
 * IDOL排行榜
 * 节约性能的获取，根据一定的时间节点来刷新
 * 设置缓存的过期时间即可
 * @param $mode
 */
function _get_idol_support_rank($mode){
    // 先取缓存
    $res = S('rank_idol_' . $mode);
    if(!$res){
        $res = D('GameSupportRank')->get_idol_rank_list($mode);
        S('rank_idol_' . $mode, $res, _get_rank_expire_time());
    }
    return $res;
}

/**
 * 玩家在当前IDOL下的排行榜(前1000名)
 * @param $uid
 * @param $idol_id
 * @param $mode
 * @return $user_rank
 * 缓存的玩家信息：uid, support, update_time, nickname, avatar
 */
function _get_user_support_rank($idol_id, $mode){
    // 先查找缓存
    $res = S('rank_idol_user_' . $idol_id . '_' . $mode);
    if(!$res){
        $res = D('GameSupportRank')->get_idol_user_rank_list($idol_id, $mode, 1000);
        // 读取对应的玩家的nickname, avatar
        foreach($res as $k => $v){
            $user_info = D('GameUser')->_get_game_user_info($v['uid'], 'nickname, avatar_url');
            $res[$k]['nickname'] = $user_info['nickname'];
            $res[$k]['avatar'] = $user_info['avatar_url'];
        }
        S('rank_idol_user_' . $idol_id . '_' . $mode, $res, _get_rank_expire_time());
    }
    return $res;
}


/**
 * 根据排行榜内容计算奖励
 * @param mixed $type 排行榜类型 support, parkour
 * @return mixed $reward_item_list 奖励物品列表
 */
function _get_reward_by_rank($uid, $type = 'support', $mode = 'week'){

    // 排行榜奖励物品ID: 41001
    $rank_reward_id = 41001;
    // 排行榜LIMIT_ID: 10006
    $rank_limit_id = 10006;
    // 先查看上一个周期的排名情况
    $expire_time = _get_expire_time_by_mode($mode, 'last');
    // 先查看保存的上个结算周期的文件
    $file_path = 'GameData/history_rank_support/' . $mode . '/' . $expire_time . '.json';
    if(file_exists($file_path)){
        $res = json_decode(file_get_contents($file_path), true);
    }
    else{
        $res = D('GameSupportRank')->get_last_rank_info($mode);
        // 保存文件
        if(!file_exists('GameData/history_rank_support/' . $mode)){
            mkdir('GameData/history_rank_support/' . $mode, 0777, true);
        }
        file_put_contents($file_path, json_encode($res));
    }
    // 找到对应的排名
    $reward_count = 0;
    foreach($res as $idol){
        foreach($idol['user_rank_list'] as $k => $v){
            // 每个明星下的排名匹配
            $idol_rank = 'rank' . $idol['rank'];
            if($v['uid'] == $uid){
                $user_rank = $k + 1;
                $reward_count += _get_config_table()->getTbRankSupport()->get($user_rank)->$idol_rank;
                break;
            }
        }
    }
    if($reward_count > 0){
        return [[$rank_reward_id, $reward_count]];
    }
    else{
        return [[10002, 100]];
    }
}

/**
 * 辅助函数，获取结算时间戳
 * @param $mode day/week/month
 * @param $type current/last
 * @return mixed $expire_time
 */
function _get_expire_time_by_mode($mode, $type = 'current'){
    if($type == 'current'){
        switch($mode){
            case 'day':
                return strtotime('tomorrow midnight');
            case 'week':
                return strtotime('next week 00:00:00');
            case 'month':
                return strtotime('first day of next month 00:00:00');
            default:
                return false;
        }
    }
    elseif($type == 'last'){
        switch($mode){
            case 'day':
                return strtotime('today midnight');
            case 'week':
                return strtotime('this week 00:00:00');
            case 'month':
                return strtotime('first day of this month 00:00:00');
            default:
                return false;
        }
    }
    else{
        return false;
    }
}

/**
 * 辅助函数，根据当前时间戳获取下一个缓存更新时间的过期时间
 */
function _get_rank_expire_time(){
    // 缓存刷新时间间隔，单位分钟
    $gap = C('RANK_REFRESH_GAP');
    // 过期时间到下一个N分钟
    $now = time();
    $currentMinute = (int) date('i', $now);
    $currentSecond = (int) date('s', $now);
    // 计算需要增加的秒数
    $expire_time = ($gap - ($currentMinute % $gap)) * 60 - $currentSecond;
    // 避免计算出0秒（当前正好是整N分钟）
    if ($expire_time <= 0) {
        $expire_time = $gap * 60;  // 直接加时间
    }
    return $expire_time;
}
/**
 * 辅助函数，根据当前关卡ID获取下一个关卡ID
 * @param mixed $stage_id
 * @return mixed
 */
function _get_next_stage($stage_id){
    $current_stage = _get_config_table()->getTbStage()->get($stage_id);
    // 如果是挑战关卡，就返回错误
    if($current_stage->type == 2){
        return false;
    }
    $chapter_stages = [];
    foreach(_get_config_table()->getTbChapter()->getDataList() as $k => $v){
        if($v->isChallenge){
            continue;
        }
        $chapter_stages = array_merge($chapter_stages, $v->stages);
    }
    // 找到当前关卡顺序
    $current_stage_index = array_search($stage_id, $chapter_stages);
    if(!$stage_id){
        return $chapter_stages[0];
    }
    // 如果下一关卡存在，返回对应的stageId
    if($chapter_stages[$current_stage_index + 1]){
        return $chapter_stages[$current_stage_index + 1];
    }
    // 如果是最后一关了，就返回当前关卡
    // 此处用于协助判断当前章节
    else{
        return $stage_id;
    }
}
/**
 * 根据用户当前的stage_info，计算当前的stage_id（就是对比stage中最后的id）
 * @param mixed $stage_info 用户当前的stage_info
 * @return mixed stage_id
 */
function _get_latest_stage_id($stage_info){
    // 获取拍扁的章节关卡id数组
    $chapter_stages = [];
    foreach(_get_config_table()->getTbChapter()->getDataList() as $k1 => $v1){
        if($v1->isChallenge){
            continue;
        }
        $chapter_stages = array_merge($chapter_stages, $v1->stages);
    }
    $latest_stage_index = -1;
    // 查看玩家的stage_info
    foreach($stage_info as $k => $v){
        $stage_config = _get_config_table()->getTbStage()->get($k);
        // 没有通关的关卡，或者是挑战关卡，就跳过
        if(!$v['status'] || (!$stage_config) || $stage_config->stageType == 2){
            continue;
        }
        $latest_stage_index = max($latest_stage_index, array_search($k, $chapter_stages));
    }
    return $chapter_stages[$latest_stage_index];
}
/**
 * 辅助函数，设置奖励缓存，设置过期时间为300秒
 * @param mixed $reward_token
 * @param mixed $reward, 设为null删除缓存
 * @return void
 */
function _set_reward_cache($reward_token, $reward){
    S($reward_token, $reward, 300);
}

/**
 * 辅助函数，获取奖励缓存
 * @param mixed $reward_token
 * @return mixed
 */

function _get_reward_cache($reward_token){
    return S($reward_token);
}

/**
 * 领取剧情关卡的通关奖励
 * @param mixed $stage_id 关卡id
 * @return mixed $reward_item_list
 */
function _get_reward_by_stage($stage_id){
    $stage_config = _get_config_table()->getTbStage()->get($stage_id);
    // 不是剧情模式，就返回false
    if($stage_config->stageType !== 1){
        return false;
    }
    $reward_res = $stage_config->parkourReward;
    if(count($reward_res) == 0){
        return false;
    }
    $reward_item_list = [];
    foreach($reward_res as $k => $v){
        $reward_item_list[$v[0]] = $v[1];
    }
    return $reward_item_list;
}
/**
 * 辅助函数，根据背包计算收藏等级
 * @param mixed $backpack 背包
 * @return mixed
 */
function _get_collect_level_by_backpack($backpack){
    // N: 2 => 1, R: 3 => 2, SR: 4 => 6, SSR: 5 => 10, SP: 6 => 10
    $quality_map = [0, 0, 1, 2, 6, 10, 10];
    $collect_point = 0;
    foreach($backpack as $k => $v){
        $item = _get_item_table()->get($k);
        if($item->primeGroup != 4){
            continue;
        }
        $collect_point += $v * $quality_map[$item->quality];
    }
    return ($collect_point - 1) / 100;
}

/**
 * 无尽模式根据距离领取奖励
 * @param mixed $stage_id 关卡id
 * @param mixed $distance 距离
 * @param mixed $rate 奖励倍率
 * @return mixed $reward_item_list
 */
function _get_reward_by_distance($stage_id, $distance, $rate = 1){
    $stage_config = _get_config_table()->getTbStage()->get($stage_id);
    $reward_config = _get_config_table()->getTbParkourReward()->get($stage_id);
    // 不是无尽模式，就返回false
    if($stage_config->stageType !== 2){
        return false;
    }
    $reward_item_list = [];
    foreach($reward_config->distance as $k => $v){
        if($distance >= $v){
            // 基础奖励
            foreach($reward_config->basicReward[$k] as $v2){
                if(!$reward_item_list[$v2[0]]){
                    $reward_item_list[$v2[0]] = $v2[1];
                }
                else{
                    $reward_item_list[$v2[0]] += $v2[1];
                }
            }
            // 加成奖励
            foreach($reward_config->dynamicReward[$k] as $v3){
                if(!$reward_item_list[$v3[0]]){
                    $reward_item_list[$v3[0]] = round($v3[1] * $rate);
                }
                else{
                    $reward_item_list[$v3[0]] += round($v3[1] * $rate);

                }
            }
        }
    }
    if(count($reward_item_list) == 0){
        return false;
    }
    return $reward_item_list;
}

/**
 * 获取公告图片列表，借助缓存
 * @return mixed $res 公告图片列表
 */
function _get_notice_image_list(){
    if($res = S('notice_image_list')){
        return $res;
    }
    $res = D('GameNoticeImage')->game_notice_image_list();
    S('notice_image_list', $res, 600);
    return $res;
}







/**************************  以下是抢鲜版专属函数 ********************************/

/**
 * du 2025.2.16
 * 获取当前有效的活动
 * Summary of _get_task_table
 * @return array $task_data 任务表数据
 */
function _get_activity_list(){
    $activity_list = [];
    // 从配置表读取活动信息
    $res = _get_config_table()->getTbEarlyAccess()->getDataMap();
    foreach($res as $k => $v){
        // 过滤有效时间
        if($v->startTime < time() && $v->endTime > time()){
            $reward = [];
            foreach($v->reward as $v2){
                $reward[$v2[0]] = $v2[1]; // 奖励数量
            }
            $v->reward = $reward;
            $v->target = 1; // 目标数量
            $activity_list[$k] = get_object_vars($v);
        }
    }
    return $activity_list;
}

/**
 * du 2025.2.16
 * 初始化用户活动
 * Summary of _init_user_activity
 * @return $user_activity 用户活动
 */
function _init_user_activity(){
    $user_activity = [];
    foreach(_get_activity_list() as $k => $v){
        if($v['startTime'] < time() && $v['endTime'] > time()){
            $user_activity[$k] = [
                'status' => 1, // 0 未完成 1 已完成
                'progress' => 1, // 进度
                'update_time' => time(), // 更新时间
            ];
        }
    }
    return $user_activity;
}

/**
 * du 2025.2.16
 * 获取奖励物品树
 * 根据品质来排
 * Summary of _get_reward_item_tree
 * @return $reward_item_list 奖励物品列表
 */
function _get_reward_item_tree(){
    $quality_map = [
        1 => 'NONE', 2 => 'N', 3 => 'R', 4 => 'SR', 5 => 'SSR', 6 => 'SP'
    ];
    $item_list = _get_item_table()->getDataList();
    $item_tree = [];
    foreach($item_list as $k => $v){
        // 先过滤货币
        if($v->type == 1) continue;
        if($v->id == 20001) continue; // 跳过抢鲜徽章(20001)
        if($v->type == 2){
            // 徽章类
            $item_tree['badge'][$quality_map[$v->quality]][$v->id] = $v;
        }elseif($v->type == 3){
            // 皮肤类
            $item_tree['skin'][$quality_map[$v->quality]][$v->id] = $v;
        }
    } 
    return $item_tree;
}

/**
 * du 2025.2.16
 * 品质概率计算并抽签
 * Summary of _get_quality_rate
 * @param mixed $rate_rule
 * @return $quality
 */
function _get_quality_draw($rate_rule){
    $random = mt_rand(1, 10000);
    // 获取抽奖的品质
    $rate = 0;
    foreach($rate_rule as $k => $v){
        // 计算各个阶梯的概率
        if($random > $rate * 10000){
            $quality = $k;
        }
        $rate += $v;
    }
    return $quality;
}

/**
 * du 2025.2.16
 * 根据抢鲜版的掉落概率来抽取物品
 * Summary of _draw_item_by_trial_rate
 * @param mixed $rule 规则 fail, new, easy, normal, hard
 * @param mixed $type 类型 badge, skin
 * @return $items 掉落物品列表
 */
function _draw_item_by_trial_rate($type, $rule){
    $quality = _get_quality_draw(C('TRIAL_REWARD_RATE')[$rule]);
    $items = _get_reward_item_tree()[$type][$quality];
    // 随机抽取一个
    $item = $items[array_rand($items)];
    return $item->id;
}

/**
 * du 2025.2.16
 * 抢鲜版专属
 * 根据背包中的物品数量来抽奖励
 * Summary of _get_reward_list_by_backpack
 * @param mixed $backpack 背包
 * @return array $reward_item_list 奖励物品列表
 */
function _get_reward_list_by_backpack($backpack){
    // 1. 某个吧唧碎片数量>10 2.神秘徽章的种类>3 hard
    // 1. 某个吧唧碎片数量>5 2.神秘徽章的种类>2 normal
    // 20021-20026 神秘徽章， 20031-20039 吧唧碎片
    $r_num = 0; // 神秘徽章数量
    $r_type = 0; // 神秘徽章种类
    $b_num = 0; // 吧唧碎片数量
    $b_max = 0; // 吧唧碎片最大数量
    foreach($backpack as $id => $num){
        if($id >= 20021 && $id <= 20026){
            $r_num += $num; 
            $r_type ++;
        }else if($id >= 20031 && $id <= 20039){
            $b_num += $num;
            $b_max = max($b_max, $num);
        }
    }   
    $rule = 'new';
    if($r_type > 0){
        $rule = 'easy';
    }
    if($r_type >= 2 || $b_max >= 5){
        $rule = 'normal';
    }
    if($r_type >= 4 || $b_max >= 10){
        $rule = 'hard'; 
    }
    // 获取奖励物品列表
    $reward_list = [];
    // 根据背包抽一次
    $reward_list[] = _draw_item_by_trial_rate('badge', $rule);
    // 剩下的给名牌徽章
    $quantity = mt_rand(2, 3);
    for($i = 0; $i < $quantity; $i++){
        $reward_list[] = _draw_item_by_trial_rate('badge', 'fail');
    }
    // 排序去重
    asort($reward_list);
    $reward_list = array_unique($reward_list);
    $reward_item_list = [];
    foreach($reward_list as $item){
        $reward_item_list[$item] = 1;
    }
    return $reward_item_list;
}

/**
 * du 2025.2.16
 * 抢鲜版专属
 * 根据背包中的物品数量来抽奖励
 * Summary of _get_reward_list_by_backpack
 * @param mixed $backpack 背包
 * @return array $reward_item_list 奖励物品列表
 */
function _get_exchange_reward_list_by_backpack($backpack){
    // 1. 某个吧唧碎片数量>10 2.神秘徽章的种类>3 hard
    // 1. 某个吧唧碎片数量>5 2.神秘徽章的种类>2 normal
    // 20021-20026 神秘徽章， 20031-20039 吧唧碎片
    $r_num = 0; // 神秘徽章数量
    $r_type = 0; // 神秘徽章种类
    $b_num = 0; // 吧唧碎片数量
    $b_max = 0; // 吧唧碎片最大数量
    $r_item = [];
    $b_item = [];
    foreach($backpack as $id => $num){
        if($id >= 20021 && $id <= 20026){
            $r_num += $num; 
            $r_type ++;
            $r_item[$id] = $num;
        }else if($id >= 20031 && $id <= 20039){
            $b_num += $num;
            $b_max = max($b_max, $num);
            $b_item[$id] = $num;
        }
    }   
    // 必出神秘徽章或者必出吧唧碎片
    $rule = 'new';
    if($r_type >= 4 || $b_max >= 10){
        $rule = 'extreme'; 
    }
    $reward_list = [];
    if($rule == 'extreme'){
        // 极限情况，必出重复什么徽章
        $reward_list[] = array_rand($r_item);
    }else{
        $reward_list[] = _draw_item_by_trial_rate('badge', $rule);
    }
    $quantity = mt_rand(3, 4);
    // 获取奖励物品列表
    for($i = 0; $i < $quantity; $i++){
        $reward_list[] = _draw_item_by_trial_rate('badge', 'fail');
    }
    // 排序去重
    asort($reward_list);
    $reward_list = array_unique($reward_list);
    $reward_item_list = [];
    foreach($reward_list as $item){
        $reward_item_list[$item] = 1;
    }
    return $reward_item_list;
}
    
?>